package sing.rabbit.provider.send;

import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import static sing.rabbit.common.configurations.DirectConfiguration.DIRECT_ROUTING_KEY;

/**
 * 这里使用 @Scope 设为多例 是 为了解决报错：Only one ConfirmCallback is supported by each RabbitTemplate <br>
 *
 * confirm 类型为 simple 时的使用演示。<br>
 *
 *
 *
 * @author xing
 * @date 2022/9/9 1:13
 */
@Profile("simple")
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DirectSimpleMessageSender {
    @Autowired
    public RabbitTemplate myRabbitTemplate;

    @Autowired
    public Queue directQueue;
    @Autowired
    private DirectExchange directExchange;

    @PostConstruct
    private void setupCallbacks() {
        myRabbitTemplate.setConfirmCallback(((correlationData, ack, cause) -> {
            if(correlationData != null) {
                System.out.println("now in confirmCallBack, ack: " + ack + ", correlationData: " + correlationData);
            } else {
                System.out.println("correlated is null");
            }
        }));
        myRabbitTemplate.setReturnsCallback(returned -> {
            Message message = returned.getMessage();
            System.out.println("now in returnCallback, return message: " + message);
        });
    }

    public void sendForConfirm () {

        myRabbitTemplate.invoke(op -> {

            String message = "for confirm message";
            // 使用绑定了队列的 routingKey，为了只看 发送到交换机的 confirm，不看 returned
            myRabbitTemplate.convertAndSend(directExchange.getName(), DIRECT_ROUTING_KEY, message);
            System.out.println("send message success: " + message);

            // 或 myRabbitTemplate.waitForConfirms(10000);
            op.waitForConfirms(10000);
            return null;
        });
    }

    public void sendForReturned () {

        myRabbitTemplate.invoke(op -> {

            String message = "for returned message";
            // 随便取一个 routingKey, 交换机无法发送消息到至少一个队列，触发 returned
            myRabbitTemplate.convertAndSend(directExchange.getName(), "forReturned", message);
            System.out.println("send message success: " + message);

            // 或 myRabbitTemplate.waitForConfirms(10000);
            op.waitForConfirms(10000);
            return null;
        });
    }
}
